function LoadMore(param) {
try{
	var that = this;
	
	this.j_view_more_button = null;
	
	var retrieving = false;
	
	var j_loadmore_container = null;
	var j_items_container = null;
	var j_loading_status = null;
	var j_view_more_container = null;
	var j_view_more_button = null;
	var j_unshown_status = null;
	var j_load_msg = null;
	
	var loadmore_data = null;
	
	var retrieve_url = "";
	var retrieve_params = {};
	var offset = 0;
	var order_by = "";
	var no_results_msg = "";
	var no_more_results_msg = "";
	var error_msg = "";
	var cur_showing_no = 0;
	var init_total = 0;
	
	var triggered_view_more_button = null;
	
	function __construct(p) {
	try{
		for(pkey in p) {
			if(pkey[0] != "_") {
				that[pkey] = p[pkey];
			}
		}
		
		that.j_view_more_button.live("click", viewMoreButtonClick);
		
	}catch(err) {
		alert(err);
	}
	}

	function init() {
	try{
		j_loadmore_container = triggered_view_more_button.closest("[data-loadmore-dom-id=loadmore-container]");
		j_items_container = j_loadmore_container.find("[data-loadmore-dom-id=items-container]").first();
		j_loading_status = j_loadmore_container.find("[data-loadmore-dom-id=loading-status]").last();
		j_view_more_container = j_loadmore_container.find("[data-loadmore-dom-id=view-more-container]").last();
		j_unshown_status = j_loadmore_container.find("[data-loadmore-dom-id=unshown-status]").last();
		j_load_msg = j_loadmore_container.find("[data-loadmore-dom-id=load-msg]").last();
		
		loadmore_data = triggered_view_more_button.data("loadmore");
		retrieve_url = loadmore_data.retrieve_url;
		retrieve_params = loadmore_data.retrieve_params;
		offset = retrieve_params.offset;
		order_by = retrieve_params.order_by;
		cur_showing_no = retrieve_params.cur_showing_no;
		init_total = retrieve_params.init_total;
		no_results_msg = loadmore_data.no_results_msg;
		no_more_results_msg = loadmore_data.no_more_results_msg;
		error_msg = loadmore_data.error_msg;
		
	}catch(err) {
		alert(err);
	}
	}
	
	function viewMoreButtonClick(e) {
	try{
		e.preventDefault();
		triggered_view_more_button = jq(this);
		init();
		j_view_more_container.hide();
		retrieve();
		
	}catch(err) {
		alert(err);
	}
	}
	
	function retrieve() {
	try{
		if(!retrieving) {
			retrieving = true;
			j_loading_status.show();
			
			jq.get(retrieve_url, retrieve_params, retrieveSuccess)
			.error(function() {
		    	// alert("Oops! An error occurred while processing your request.");
				j_load_msg.text(error_msg);
				j_load_msg.show();
				
		    })
		    .complete(function() {
		   		// complete
				j_loading_status.hide();
				retrieving = false;
		    });
		}
	}catch(err) {
		alert(err);
	}
	}
	
	function retrieveSuccess(data) {
	try{
		jq.each(data.items, function(index, item) {
			j_items_container.append(item.html);
		});
		
		cur_showing_no += data.items.length;
		
		loadmore_data.retrieve_params["cur_showing_no"] = cur_showing_no;
		triggered_view_more_button.attr("data-loadmore", jsonStringify(loadmore_data));

		j_unshown_status.text(getUnshowingStatus());
		
		if(cur_showing_no == 0) {
			j_load_msg.text(no_results_msg);
			j_load_msg.show();
		}else if(cur_showing_no < init_total) {
			j_view_more_container.show();
		}else if(cur_showing_no >= init_total) {
			j_load_msg.text(no_more_results_msg);
			j_load_msg.show();
		}
	}catch(err) {
		alert(err);
	}
	}
	
	function getUnshowingStatus() {
	try{
		return init_total - cur_showing_no;
	}catch(err) {
		alert(err);
	}
	}
	
	// implement JSON.stringify serialization
	function jsonStringify(obj) {
	try{
		var t = typeof (obj);
	    if (t != "object" || obj === null) {
	        // simple data type
	        if (t == "string") obj = '"'+obj+'"';
	        return String(obj);
	    }
	    else {
	        // recurse array or object
	        var n, v, json = [], arr = (obj && obj.constructor == Array);
	        for (n in obj) {
	            v = obj[n]; t = typeof(v);
	            if (t == "string") v = '"'+v+'"';
	            else if (t == "object" && v !== null) v = JSON.stringify(v);
	            json.push((arr ? "" : '"' + n + '":') + String(v));
	        }
	        return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
	    }
	}catch(err) {
		alert(err);
	}
	}
	
	__construct(param);
	
}catch(err) {
	alert(err);
}
}

	
